package com.example.selfPractise;

/**
 * 雪花ID的结构
 * 符号位-41bit时间戳-10bit机器ID-12bit序列号
 */
public class SnowflakeIdGenerator {
    // 定义雪花ID的各部分位数
    private static final long TIMESTAMP_BITS = 41L;
    private static final long NODE_ID_BITS = 10L;
    private static final long SEQUENCE_BITS = 12L;

    //定义起始时间戳（可根据实际情况调整）
    private static final long EPOCH = 1609459200000L;

    // 定义最大取值范围
    private static final long MAX_NODE_ID = (1L << NODE_ID_BITS) - 1;
    private static final long MAX_SEQUENCE = (1L << SEQUENCE_BITS) - 1;

    //定义偏移量
    private static final long TIMESTAMP_SHIFT = NODE_ID_BITS + SEQUENCE_BITS;
    private static final long NODE_ID_SHIFT = SEQUENCE_BITS;

    /**
     * √ final、static区别，何时加哪个、并用；
     * return、break区别，何时用
     * private final long nodeId;   报错，去掉final就正常
     *  private static final Object[] EMPTY_ELEMENTDATA = {};     为什么static final
     *
     * 何时加synchronized  方法、代码块;  synchronized关键字和ReentrantLock有什么区别
     * volatile、JMM、Synchronized、CAS、线程池
     *
     * HashMap的工作原理及其内部结构；Vector和ArrayList有什么区别
     * hashmap线程安全吗，有什么替代的，知道concurrenthashmap如何实现线程安全的吗；ConcurrentHashMap怎么做并发处理的（介绍了一下分段思想和锁桶头）
     * ThreadL ocal；HashMap为什么不安全，如何改进减端以及ConcurrentHashMap
     *
     * try、catch、finally逻辑
     */
    private final long nodeId;
    private long lastTimestamp = -1L;
    private long sequence = 0L;

    public SnowflakeIdGenerator(long nodeId) {
        if (nodeId < 0 || nodeId > MAX_NODE_ID) {
            throw new IllegalArgumentException("Invalid node ID");
        }
        this.nodeId = nodeId;
    }

    public synchronized long generateId() {
        long currentTimestamp = timestamp();
        if (currentTimestamp < lastTimestamp) {
            throw new IllegalStateException("Clock moved backwards");
        }
        if (currentTimestamp == lastTimestamp) {
            sequence = (sequence + 1) & MAX_SEQUENCE;
            if (sequence == 0) {
                currentTimestamp = untilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }
        lastTimestamp = currentTimestamp;
        return ((currentTimestamp - EPOCH) << TIMESTAMP_SHIFT) |
                (nodeId << NODE_ID_SHIFT) |
                sequence;
    }

    private long timestamp() {
        return System.currentTimeMillis();
    }

    private long untilNextMillis(long lastTimestamp) {
        long currentTimestamp = timestamp();
        while (currentTimestamp <= lastTimestamp) {
            currentTimestamp = timestamp();
        }
        return currentTimestamp;
    }

    public static void main(String[] args) {
        // 创建一个雪花 ID 生成器实例，传入节点 ID
        SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1);
        // 生成 ID
        long id = idGenerator.generateId();
        System.out.println(id);    //423799457432211456

    }


}
